/**
 * 
 */
package util;
import static java.lang.Math.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;

/**
 * Allows the creation and manipulation of 2-dimensional vectors.
 * @author pheiffer
 */

public class Vec2F 
{
	static float Distance2(final Vec2F v1,final Vec2F v2)
	{
		return v1.sub(v2).mag2();
	}
	static float Distance(final Vec2F v1,final Vec2F v2)
	{
	    	return (float)hypot(v1.x-v2.x,v1.y-v2.y);
	}
	
	private final float x,y;
	
	public Vec2F(float x,float y)
	{
		this.x=x;
		this.y=y;
	}
	public Vec2F(Vec2F vec)
	{
		this.x=vec.x;
		this.y=vec.y;
	}

	public Vec2F(Vec2I vec2I)
	{
		this.x = (float)vec2I.getX();
		this.y = (float)vec2I.getY();
	}
	public Vec2F GetTransform(AffineTransform t)
	{
		Point2D.Float result=new Point2D.Float();
		t.transform(new Point2D.Float(x,y),result);
		return new Vec2F((float)result.getX(),(float)result.getY());
	}

	final public float getX() {
		return x;
	}
	final public float getY() {
		return y;
	}

	public static Vec2F add(Vec2F v1,Vec2F v2)
	{
		return new Vec2F(v1.x+v2.x,v1.y+v2.y);
	}
	public static Vec2F sub(Vec2F v1,Vec2F v2)
	{
		return new Vec2F(v1.x-v2.x,v1.y-v2.y);
	}
	public static float dot(Vec2F v1,Vec2F v2)
	{
		return v1.x*v2.x+v1.y*v2.y;
	}
	public static Vec2F scale(Vec2F v1,float scale)
	{
		return new Vec2F(v1.x*scale,v1.y*scale);
	}
	
	/**
	 * Assumes counter-clockwise is positive ie. if v2 is counter-clockwise from
	 * v1 then the result will be positive.
	 * @author Stephen Pheiffer
	 * @param v1
	 * @param v2
	 * @return sin of angle between v1 and v2.
	 */
	public static float cross(Vec2F v1, Vec2F v2)
	{
		return (v1.x * v2.y) - (v1.y * v2.x);
	}
	public boolean equals(Vec2F v1)
	{
		return v1.x==x && v1.y==y;
		
	}
	public Vec2F add( Vec2F v2)
	{
		return new Vec2F(x+v2.x,y+v2.y);
	}
	public Vec2F sub(Vec2F v2)
	{
		return new Vec2F(x-v2.x,y-v2.y);
	}
	public float dot(Vec2F v2)
	{
		return x*v2.x+y*v2.y;
	}
	public Vec2F scale(float scale)
	{
		return new Vec2F(x*scale,y*scale);
	}
	public Vec2F scale(Vec2I scale)
	{
		return new Vec2F(x*scale.getX(),y*scale.getY());
	}
	public Vec2F scale(Vec2F scale)
	{
		return this.scale(scale.x,scale.y);
	}
	public Vec2F scale(float x, float y)
	{
		return new Vec2F(this.x*x,this.y*y);
	}
	
	/**
	 * Get orthogonal vector (rotated clockwise)
	 * @author Stephen Pheiffer
	 * @return
	 */
	public Vec2F ortho()
	{
		return new Vec2F(-y,x);
	}
	public float mag2()
	{
		return x*x+y*y;
	}
	public float mag()
	{
		return (float)hypot(x,y);
	}
	public Vec2F unit()
	{
		return scale(1.0f/this.mag());
	}
	public Vec2F rotate(float angle)
	{
		return new Vec2F(x*(float)cos(angle)-y*(float)sin(angle),x*(float)sin(angle)+y*(float)cos(angle));
	}
	public Vec2F rotate(float cosAngle,float sinAngle)
	{
		return new Vec2F(x*cosAngle-y*sinAngle,x*sinAngle+y*cosAngle);
	}
	public float getAngle()
	{
		return (float)atan2(y,x);
	}
	public float getAngleDifference(Vec2F v2)
	{
		float angle;
		angle = v2.getAngle() - getAngle();
		if(angle < 0.0)
			angle += 2 * PI;
		return angle;
	}

	@Override
	public String toString()
	{
		return String.format("%f , %f", x,y);
	}
	

}
